package com.exmaple.deal.filter;

import javax.servlet.http.HttpServletResponse;

import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

@Component
public class RateLimitZuulFilter extends ZuulFilter {

	private final RateLimiter rateLimiter = RateLimiter.create(1000.0);
	
	/**
	    *   前置过滤器
	 */
	@Override
	public String filterType() {
		return FilterConstants.PRE_TYPE;
	}
	
	/**
	 * 最高优先级
	 */
	@Override
	public int filterOrder() {
		return Ordered.HIGHEST_PRECEDENCE;
	}
	
	/**
	 * 限流开关
	 */
	@Override
	public boolean shouldFilter() {
		// 这里可以考虑弄个限流开启的开关，开启限流返回true，关闭限流返回false，你懂的。
		return true;
	}

	@Override
	public Object run() {
		try {
			RequestContext currentContext = RequestContext.getCurrentContext();
			HttpServletResponse response = currentContext.getResponse();
			//请求上限逻辑
			if (!rateLimiter.tryAcquire()) {
				HttpStatus httpStatus = HttpStatus.TOO_MANY_REQUESTS;
				
				response.setContentType(MediaType.TEXT_PLAIN_VALUE);
				response.setStatus(httpStatus.value());
				response.getWriter().append(httpStatus.getReasonPhrase());

				currentContext.setSendZuulResponse(false);

				throw new ZuulException(httpStatus.getReasonPhrase(), httpStatus.value(), httpStatus.getReasonPhrase());
			}
			
			//正常处理请求逻辑
			currentContext.setSendZuulResponse(true);// 对该请求进行路由
			currentContext.setResponseStatusCode(200);
			currentContext.set("isSuccess", true);// 设值，让下一个Filter看到上一个Filter的状态
			return null;
			
		} catch (Exception e) {
			ReflectionUtils.rethrowRuntimeException(e);
		}
		return null;
	}
}